package order

import (
	"context"

	"mall/service/backend/api/internal/logic/order/util"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/api/internal/utils/parse"
	"mall/service/backend/common/i18n"
	"mall/service/order/rpc/orderclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetOrderListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetOrderListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetOrderListLogic {
	return &GetOrderListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetOrderListLogic) GetOrderList(req *types.OrderListReq) (*types.OrderListResp, error) {
	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	orderBys := util.ParseSorter(req.Sorter)
	filterBys := util.ParseFilter(req.Filter, req.Type)

	var tradeState *uint32
	if req.TradeState != nil {
		tradeState = req.TradeState
	}

	data, err := l.svcCtx.OrderRpc.BackendGetOrderList(l.ctx, &orderclient.BackendOrderListReq{
		Page:       page,
		PageSize:   pageSize,
		Ids:        req.OrderIds,
		Sn:         req.Sn,
		TradeState: tradeState,
		OrderBy:    orderBys,
		FilterBy:   filterBys,
	})
	if err != nil {
		return nil, err
	}

	resp := &types.OrderListResp{
		BaseDataInfo: types.BaseDataInfo{
			Success: true,
			Msg:     l.svcCtx.Trans.Trans(l.ctx, i18n.Success),
		},
		Data: types.OrderListInfo{
			BaseListInfo: types.BaseListInfo{
				Current:  page,
				PageSize: pageSize,
				Total:    data.GetTotal(),
			},
			StatusStatisticMap: data.StatusStatisticMap,
		},
	}

	if len(data.List) > 0 {
		for _, trade := range data.List {
			var skus []*types.OrderSkuInfo
			if len(trade.Skus) > 0 {
				for _, v := range trade.Skus {
					productTypeText := util.GetProductTypeText(v.ProductType)
					skus = append(skus, &types.OrderSkuInfo{
						Id:             v.Id,
						OrderId:        v.OrderId,
						ProductCode:    v.ProductCode,
						SkuId:          v.SkuId,
						SkuCode:        v.SkuCode,
						Sku:            v.Sku,
						ImageId:        v.ImageId,
						ImageUrl:       v.ImageUrl,
						ProductId:      v.ProductId,
						EntryId:        v.EntryId,
						Title:          v.Title,
						Slug:           v.Slug,
						ProductType:    v.ProductType,
						TypeText:       productTypeText,
						BrandId:        v.BrandId,
						BrandTitle:     v.BrandTitle,
						BrandSlug:      v.BrandSlug,
						GemPrice:       v.GemPrice,
						RetailPrice:    v.RetailPrice,
						Quantity:       v.Quantity,
						Weight:         v.Weight,
						TradeState:     v.TradeState,
						Status:         v.Status,
						RefundAmount:   v.RefundAmount,
						RefundQuantity: v.RefundQuantity,
					})
				}
			}
			var addresses []*types.OrderAddressInfo
			if len(trade.Addresses) > 0 {
				for _, v := range trade.Addresses {
					addresses = append(addresses, &types.OrderAddressInfo{
						Id:         v.Id,
						OrderId:    v.OrderId,
						UserId:     v.UserId,
						Consignee:  v.Consignee,
						Mobile:     v.Mobile,
						Province:   v.Province,
						City:       v.City,
						District:   v.District,
						Address:    v.Address,
						PostalCode: v.PostalCode,
						RegionCode: v.RegionCode,
						Label:      v.Label,
					})
				}
			}
			var discounts []*types.OrderDiscountInfo
			if len(trade.Discounts) > 0 {
				for _, v := range trade.Discounts {
					discounts = append(discounts, &types.OrderDiscountInfo{
						Id:               v.Id,
						OrderId:          v.OrderId,
						SkuId:            v.SkuId,
						ProductId:        v.ProductId,
						Title:            v.Title,
						Slug:             v.Slug,
						ActivityId:       v.ActivityId,
						ActivityRuleId:   v.ActivityRuleId,
						CouponTemplateId: v.CouponTemplateId,
						CouponId:         v.CouponId,
						CouponAmount:     v.CouponAmount,
						ActivityAmount:   v.ActivityAmount,
						IntegralAmount:   v.IntegralAmount,
						DiscountAmount:   v.DiscountAmount,
						Integrals:        v.Integrals,
					})
				}
			}
			var adjustments []*types.OrderAdjustmentInfo
			if len(trade.Adjustments) > 0 {
				for _, v := range trade.Adjustments {
					adjustments = append(adjustments, &types.OrderAdjustmentInfo{
						Id:         v.Id,
						OrderId:    v.OrderId,
						Amount:     v.Amount,
						Memo:       v.Memo,
						Status:     v.Status,
						OperatedBy: v.OperatedBy,
						OperatedAt: v.OperatedAt,
					})
				}
			}
			var payments []*types.OrderPaymentInfo
			if len(trade.Payments) > 0 {
				for _, v := range trade.Payments {
					payments = append(payments, &types.OrderPaymentInfo{
						Id:      v.Id,
						OrderId: v.OrderId,
						No:      v.No,
						Amount:  v.Amount,
						Type:    v.Type,
						Name:    v.Name,
						Code:    v.Code,
						PaidAt:  v.PaidAt,
					})
				}
			}
			var shipments []*types.OrderShipmentInfo
			if len(trade.Shipments) > 0 {
				for _, v := range trade.Shipments {
					shipments = append(shipments, &types.OrderShipmentInfo{
						Id:        v.Id,
						OrderId:   v.OrderId,
						No:        v.No,
						Type:      v.Type,
						Name:      v.Name,
						Code:      v.Code,
						UpdatedAt: v.UpdatedAt,
					})
				}
			}
			var logs []*types.OrderOperateLogInfo
			if len(trade.Logs) > 0 {
				for _, v := range trade.Logs {
					logs = append(logs, &types.OrderOperateLogInfo{
						Id:         v.Id,
						OrderId:    v.OrderId,
						TradeState: v.TradeState,
						NewState:   v.NewState,
						Type:       v.Type,
						Name:       v.Name,
						Code:       v.Code,
						Status:     v.Status,
						Memo:       v.Memo,
						OperatedBy: v.OperatedBy,
						OperatedAt: v.OperatedAt,
					})
				}
			}
			var tradeStateText *string
			if trade.TradeState != nil {
				tradeStateText = util.GetTradeStateText(trade.TradeState)
			}
			var orderTypeText *string
			if trade.OrderType != nil {
				orderTypeText = util.GetOrderTypeText(trade.OrderType)
			}
			option := util.GetOptionByTradeState(trade.TradeState)
			resp.Data.List = append(resp.Data.List, &types.OrderInfo{
				BaseIDInfo: types.BaseIDInfo{
					Id:         trade.Id,
					CreatedAt:  trade.CreatedAt,
					UpdatedAt:  trade.UpdatedAt,
					DeletedAt:  trade.DeletedAt,
					CanRemove:  option.CanRemove,
					CanRestore: option.CanRestore,
				},
				ParentId:        trade.ParentId,
				UserId:          trade.UserId,
				UserRank:        trade.UserRank,
				Buyer:           trade.Buyer,
				Sn:              trade.Sn,
				OrderType:       trade.OrderType,
				OrderTypeText:   orderTypeText,
				SourceType:      trade.SourceType,
				Total:           trade.Number,
				GemAmount:       trade.GemAmount,
				RetailAmount:    trade.RetailAmount,
				Freight:         trade.Freight,
				DiscountAmount:  trade.DiscountAmount,
				AdjustAmount:    trade.AdjustAmount,
				ActualAmount:    trade.ActualAmount,
				BalanceAmount:   trade.BalanceAmount,
				RefundAmount:    trade.RefundAmount,
				Gems:            trade.Gems,
				TradeState:      trade.TradeState,
				TradeStateText:  tradeStateText,
				Remark:          trade.Remark,
				SellerMemo:      trade.SellerMemo,
				PaidAt:          trade.PaidAt,
				ShippedAt:       trade.ShippedAt,
				DeliveredAt:     trade.DeliveredAt,
				ConfirmedAt:     trade.ConfirmedAt,
				ReviewedAt:      trade.ReviewedAt,
				FulfilledAt:     trade.FulfilledAt,
				ClosedAt:        trade.ClosedAt,
				AutoComfirmDays: trade.AutoComfirmDays,
				Growth:          trade.Growth,
				Integrals:       trade.Integrals,
				Synced:          trade.Synced,
				CanAdjust:       option.CanAdjust,
				CanSync:         option.CanSync,
				Skus:            skus,
				Addresses:       addresses,
				Discounts:       discounts,
				Adjustments:     adjustments,
				Payments:        payments,
				Shipments:       shipments,
				Logs:            logs,
			})
		}
	}

	return resp, nil
}
